use crate::strategies::{Random, RoundRobin, WeightedRoundRobin, ConsistentHash};
use rustcloud_core::{LoadBalancer, LoadBalancerStrategy, ServiceInstance, ServiceResult, StrategyInfo};
use std::sync::Arc;

/// 负载均衡器管理器
pub struct LoadBalancerManager {
    strategy: LoadBalancerStrategy,
    round_robin: Arc<RoundRobin>,
    random: Arc<Random>,
    weighted_round_robin: Arc<WeightedRoundRobin>,
    consistent_hash: Arc<ConsistentHash>,
}

impl LoadBalancerManager {
    pub fn new(strategy: LoadBalancerStrategy) -> Self {
        Self {
            strategy,
            round_robin: Arc::new(RoundRobin::new()),
            random: Arc::new(Random::new()),
            weighted_round_robin: Arc::new(WeightedRoundRobin::new()),
            consistent_hash: Arc::new(ConsistentHash::new()),
        }
    }

    pub fn set_strategy(&mut self, strategy: LoadBalancerStrategy) {
        self.strategy = strategy;
    }
    
    pub fn get_strategy(&self) -> LoadBalancerStrategy {
        self.strategy
    }
}

#[async_trait::async_trait]
impl LoadBalancer for LoadBalancerManager {
    async fn select(
        &self,
        service_name: &str,
        instances: &[ServiceInstance],
    ) -> ServiceResult<Option<ServiceInstance>> {
        match self.strategy {
            LoadBalancerStrategy::RoundRobin => {
                self.round_robin.select(service_name, instances).await
            },
            LoadBalancerStrategy::Random => {
                self.random.select(service_name, instances).await
            },
            LoadBalancerStrategy::WeightedRoundRobin => {
                self.weighted_round_robin.select(service_name, instances).await
            },
            LoadBalancerStrategy::ConsistentHash => {
                self.consistent_hash.select(service_name, instances).await
            },
        }
    }

    fn name(&self) -> &str {
        match self.strategy {
            LoadBalancerStrategy::RoundRobin => self.round_robin.name(),
            LoadBalancerStrategy::Random => self.random.name(),
            LoadBalancerStrategy::WeightedRoundRobin => self.weighted_round_robin.name(),
            LoadBalancerStrategy::ConsistentHash => self.consistent_hash.name(),
        }
    }
    
    fn get_strategy_info(&self) -> StrategyInfo {
        match self.strategy {
            LoadBalancerStrategy::RoundRobin => self.round_robin.get_strategy_info(),
            LoadBalancerStrategy::Random => self.random.get_strategy_info(),
            LoadBalancerStrategy::WeightedRoundRobin => self.weighted_round_robin.get_strategy_info(),
            LoadBalancerStrategy::ConsistentHash => self.consistent_hash.get_strategy_info(),
        }
    }
}
